#include <stdio.h>
#include <string.h>
#include "evaluater.h"

/*
typedef struct Eval_Entry_Tag 
{
    TypeFunc is_type;
    EvalFunc eval;
} Eval_Entry;
*/

/******************************************************************************
 * BEGIN OF TYPE FUNCTION 
*******************************************************************************/

static bool is_symbol( char* p )
{
    return *p == '(';
}

static bool is_definition( Exp exp )
{
    char *p = exp.p + exp.s;
    char def[] = "DEFINE";
    return 0 == memcmp( p, def, exp.l );
}

static bool is_assignment( Exp exp )
{
    char *p = exp.p + exp.s;
    char set[] = "SET!";
    return 0 == memcmp(p, set, exp.l);
}

static bool is_if( Exp exp )
{
    return 0 == 
        memcmp( exp.p+exp.s, "IF", exp.l );
}

static bool is_lambda( Exp exp)
{
    return 0 ==
        memcmp( exp.p+exp.s, "LAMBDA", exp.l);
}

static bool is_begin(Exp exp)
{
    return 0 ==
        memcmp( exp.p+exp.s, "BEGIN", exp.l);
}

static bool is_application( Exp exp )
{
    /* it should be always true, isn't it?*/
    return 1;
}
    
static bool is_self_eval( Exp exp ) 
{
    char *p = exp.p + exp.s;
    return ( /* is exp a number? */ 
        (*p >= '0' && *p <= '9')
        || *p == '+' 
        || *p == '-')
        /* is exp a string? */
        || ( *p == '"');
}

static bool is_quoted( Exp exp)
{
    char *p = exp.p + exp.s;
    return *p == '`' ||
        0 == memcmp( p, "QUOTE", exp.l);
}

static bool is_variable( Exp exp )
{
    return 0;
}

/******************************************************************************
 * END OF TYPE FUNCTION 
*******************************************************************************/

/******************************************************************************
 * BEGIN OF EVAL FUNCTION 
*******************************************************************************/
static Ret ev_definition( Exp exp, Env env)
{
    
}
static Ret ev_self_eval( Exp exp, Env env )
{

}

static Ret ev_variable( Exp exp, Env env)
{}
static Ret ev_quoted( Exp exp, Env env ){}
static Ret ev_assignment( Exp exp, Env env){}

static Ret ev_if( Exp exp, Env env){}
static Ret ev_lambda( Exp exp, Env env){}
static Ret ev_begin( Exp exp, Env env){}
static Ret ev_application( Exp exp, Env env){}



#define FIRST_EXP_COUNT 6

TypeFunc first_exp_t[FIRST_EXP_COUNT] = { is_definition,
                                          is_assignment,
                                          is_if,
                                          is_lambda,
                                          is_begin,
                                          is_application };

EvalFunc first_ev_t[FIRST_EXP_COUNT] = { ev_definition,
                                         ev_assignment,
                                         ev_if,
                                         ev_lambda,
                                         ev_begin,
                                         ev_application };

#define REST_EXP_COUNT 3
TypeFunc rest_exp_t[REST_EXP_COUNT] = { is_self_eval,
                                        is_quoted,
                                        is_variable };

EvalFunc rest_ev_t[REST_EXP_COUNT] = { ev_self_eval,
                                       ev_quoted,
                                       ev_variable };


/*
Ret ev_variable( Exp exp, Env env)
{
    return lookup_variable_value( exp, env );
}

Ret ev_quoted( Exp exp, Env env )
{
    return text_of_quotation( exp );
}

Ret ev_lambda( Exp exp, Env env )
{
    Env unev = lambda_parameters( exp );
    exp = lambda_body( exp );
    return make_procedure( unev, exp, env );
}
*/
/*
void eval_dispatch( Exp exp, Env env )
{
    int i = 0;
    for ( i = 0; i < TABLE_COUNT; i++ )
    {
        if ( (*(eval_table[i].is_type))( exp ) )
        {
            exp = (*(eval_table[i]).eval)( exp, env );
            return;
        }
    }
    printf("Unknown Expression!");
}
*/
int eval( char* p, Env env )
{
    Exp exp = { p, 0, -1 };
    while ( *p != '\0' )
    {
        switch( *p )
        {
        case ' ':
        case '\n':  /*skip space*/
            printf("skip white space!\n");
            p++;
            break;
        case ';': /* comment line */
            while ( *p != '\n' && *p != '\0' )
                p++;
            break;
        case '(': /* get a list */
            p++;
            while ( *p == '\n' && *p == ' ')
                p++;
            /*TODO: Handle Empty List () */
            exp.p = p;
            exp.s = 0;
            exp.l = -1;
            /*eval_dispath( exp, env );*/
            break;
        case ')': /* get out a list */
            return;
        default: /* an atom*/
            
            printf("get an atom!\n");
            break;
        }
        p++;
    }
    return 0;
}

